Concurrent programming for shared-memory multiprocessors can include the ability for multiple threads to access the same data. The multiple threads execute on multiple processors, multiple processor cores, or other classes of parallel hardware architecture involving a memory system shared among the processors. The shared-memory model is the most commonly deployed method of multithreaded communication. In such systems, concurrent threads can attempt to access and modify the same data in the shared-memory and often implement functionality using modifications to memory locations and input/output on real shared hardware devices. Both techniques are called side effects. Side effects can lead to race conditions and other undesired effects in concurrent programming, due to simultaneous access to these shared resources.
A major difficulty in implementing concurrent programming involves regulating access to these shared resources to avoid undesired effects. Developers often rely on a form of synchronization for concurrency safety. Synchronization often involves the use of locks, which is a form of pessimistic concurrency control mechanism that ensures data cannot be simultaneously accessed; this guarantees that one thread reading data won't see state as it is being updated by another. Synchronization provides safety often at the expense of performance and scalability. Newer synchronization technologies, such as those based on optimistic concurrency control (like Software Transaction Memory) provide superior performance and scalability than locks. But all contemporary synchronization mechanisms, even optimistic concurrency control, eventually cause issues in concurrent programming: when threads wait for another, scalability drops; shared-memory systems use caches whose performance drops significantly when threads share access to memory; and so on.